"""
1. 文件概述
该文件是经济数据分析可视化模块，基于matplotlib实现多种统计图表的自动化生成，支持折线图、柱状图、季节性分析图等多种图表类型，主要用于月度经济分析PPT的图表生成。

2. 核心功能
提供统一的图表样式配置（中文字体支持、边框设置、颜色主题）
实现多种经济指标可视化模板
支持数据自动读取、日期格式化和图表保存
包含智能标注系统，自动标注关键数据点

3. 主要函数说明
| 函数名 | 功能描述 | 主要参数 | |--------|----------|----------| 
| less_three_line_plot | 生成最多3条线的折线图 | theme, show_period, filter_cols, title, y_label, save_name | 
| less_three_bar_plot | 生成最多3类别的柱状图 | theme, show_period, filter_cols, title, y_label, save_name, width, unit | 
| plot_monthly_sesaonal_data | 生成月度季节性分析图 | theme, name, title, x_label, y_label, save_name | 
| plot_compare_bar_with_last_peirod | 生成与上期对比的横向柱状图 | theme, filter_cols, use_cols, title, y_label, save_name | 
| plot_simple_bar_by_col | 生成简单单列柱状图 | theme, filter_cols, use_cols, title, y_label, save_name | 
| plot_stack_col | 生成堆叠柱状图 | theme, filter_cols, use_cols, title, y_label, save_name, show_period |

4. 辅助功能
日期处理：get_first_day_of_month 转换日期为每月第一天
格式化工具：yearly_formatter, left_formatter 等自定义日期格式化函数
路径管理：自动创建按日期和主题分类的图表保存目录

6. 依赖项
matplotlib.pyplot
pandas
numpy
datetime
utils模块（search_data, ensure_folder_exists等）

7. 注意事项
图表默认保存路径：plot/plot_当前日期/主题名称/
支持自动处理中文显示（SimHei字体）
所有函数返回图片保存路径列表，便于批量插入PPT

"""


import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from matplotlib.ticker import FuncFormatter
import pandas as pd
from datetime import datetime
from utils import ensure_folder_exists, search_data, get_today_date
import numpy as np


# 设置中文字体和负号显示
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体字体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题


def get_first_day_of_month(input_date):
    """
    输入一个日期，返回该日期所在月份的第一天。

    参数:
    input_date (datetime.datetime 或 datetime.date): 输入的日期。

    返回:
    datetime.date: 输入日期所在月份的第一天。
    """
    if isinstance(input_date, datetime):
        input_date = input_date.date()
    return input_date.replace(day=1)


def yearly_formatter(x, pos=None):
    """
    x: matplotlib 内部日期表示（浮点数）
    pos: 位置参数（可忽略）
    """
    dt = mdates.num2date(x)  # 将浮点数转换为日期对象
    return f"\n{dt.year}年"


# 自定义格式化函数
def left_formatter(x, pos=None):
    """ 
    x: matplotlib 内部日期表示（浮点数）
    pos: 位置参数（可忽略）
    """
    dt = mdates.num2date(x)
    month = mdates.num2date(x).month
    if month == 1:
        return f"{month}月\n{dt.year}年"
    if month in [1, 4, 7, 10]:
        return f"{month}月"
    return ''


def mid_formatter(x, pos=None):
    """ 
    x: matplotlib 内部日期表示（浮点数）
    pos: 位置参数（可忽略）
    """
    month = mdates.num2date(x).month
    dt = mdates.num2date(x)
    if month == 1:
        return f"\n{dt.year}年"
    if month in [2, 5, 8, 11]:
        return f"{month}月"

    return ''


def right_formatter(x, pos=None):
    """
    x: matplotlib 内部日期表示（浮点数）
    pos: 位置参数（可忽略）
    """
    dt = mdates.num2date(x)
    month = mdates.num2date(x).month
    
    if month == 1:
        return f"\n{dt.year}年"
    if month in [3, 6, 9, 12]:
        return f"{month}月"

    return ''


monthly_adaptive_formatter = {
    1:left_formatter,
    2:mid_formatter,
    3:right_formatter,
    4:left_formatter,
    5:mid_formatter,
    6:right_formatter,
    7:left_formatter,
    8:mid_formatter,
    9:right_formatter,
    10:left_formatter,
    11:mid_formatter,
    12:right_formatter  
}


def less_three_line_plot(
    theme, show_period, filter_cols, title, y_label, save_name, 
    use_cols=None,
    colors = ['#8B0000', '#00008B', '#808080']
    ):
    """_summary_
        
    Args:
        theme (_type_): 生产测_工业
        
    show_period = 24
    theme = '生产测_工业'
    filter_cols = ['工业增加值当月同比（合并1-2月）']
    title = '工业增加值当月同比（合并1-2月）'
    y_label = '%'
    save_name = '工业增加值当月同比'    
    """
    
    find_path = search_data(theme)
    find_data = pd.read_excel('cache/' + find_path, index_col=0)

    df1 = find_data.loc[:,filter_cols]
    df1 = df1.dropna()
    
    if len(df1) > show_period:
        df1 = df1[-show_period:]
    
    if use_cols is not None:
        df1.columns = use_cols
    
    # 将索引转换为每月的第一天
    if isinstance(df1.index, pd.DatetimeIndex):
        df1.index = df1.index.to_period('M').to_timestamp()
        df1.index = pd.to_datetime(df1.index)
    
    # 按最后一行数据排序
    df1 = df1.iloc[:, df1.iloc[-1].argsort()[::-1]]
    
    plt.figure(figsize=(12, 6))
    
    colors = colors[:len(df1.columns)]  # 确保颜色列表长度与列数相匹配
    lines = []
    for i, col in enumerate(df1.columns):
        line = plt.plot(df1.index, df1[col], color=colors[i], linestyle='-',
                        linewidth=2,)
        lines.append(line)

    # 标注最后一期数据,并添加箭头,并根据数据大小调整偏移
    last_index = df1.index[-1]
    y_offset_dic = {}
    y_dic = {}
    for i, (line, col) in enumerate(zip(lines, df1.columns)):
        y = df1[col].iloc[-1]
        prev_y = df1[col].iloc[-2]  # 获取倒数第二期数据
        arrow = '↑' if y > prev_y else '↓' if y < prev_y else ''
        if arrow == '↑':
            color = 'red'
        elif arrow == '↓':
            color = 'green'
        else:
            color = 'black'
        
        if i == 0:
            y_offset_dic[i] = 0
            y_dic[i] = y
        else:
            if abs(y - y_dic[i-1]) < 0.5:
                gap = 12
            else:
                gap = 0
            y_dic[i] = y
            y_offset_dic[i] = y_offset_dic.get(i-1, 0) - gap
        offset_x = 5  # 根据数据索引动态调整x轴偏移
        
        plt.annotate(
            f'{y:.1f}%{arrow}', 
            xy=(last_index, y), 
            xytext=(offset_x, y_offset_dic[i]),
            textcoords='offset points', 
            ha='left', 
            va='bottom', 
            color=color, 
            fontsize=8
            )

    # 设置图表标题和标签
    plt.title(title)
    # plt.xlabel('日期')
    plt.ylabel(y_label)
    plt.legend(df1.columns, frameon=False)

    # 去除绘图的边框
    # 仅去除右侧和上侧的边框
    ax = plt.gca()
    ax.spines['right'].set_visible(False)
    ax.spines['top'].set_visible(False)

    # # 确保主定位器和数据范围匹配
    # ax.xaxis.set_major_locator(mdates.YearLocator())
    # ax.xaxis.set_major_formatter(FuncFormatter(yearly_formatter))
    # 确保次定位器和数据范围匹配
    ax.xaxis.set_major_locator(mdates.MonthLocator())
    latest_month = df1.index[-1].month
    adap_formatter = monthly_adaptive_formatter[latest_month]
    ax.xaxis.set_major_formatter(FuncFormatter(adap_formatter))

    # 设置横向刻度
    plt.xticks(rotation=0)
    plt.grid(False)
    
    dir_path = f"plot\plot_{get_today_date()}"
    dir_theme_path = f"{dir_path}\{theme}"
    ensure_folder_exists(dir_path)
    ensure_folder_exists(dir_theme_path)
    # 将厘米转换为英寸
    li = []
    for h in [9]:
        w = 15
        # h = 9
        width_inch = w / 2.54
        height_inch = h / 2.54
        plt.gcf().set_size_inches(width_inch, height_inch)
        path = f'{dir_theme_path}\{save_name}_{w}_{h}.png'
        plt.savefig(path, dpi=300, bbox_inches='tight')
        li.append(path)
    plt.close()
    return li


def less_three_bar_plot(
    theme, show_period, filter_cols, title, y_label, save_name, width, unit,
    use_cols=None,):
    """_summary_
        
    Args:
        theme (_type_): 生产测_工业
        
    show_period = 24
    theme = '生产测_工业'
    filter_cols = ['工业增加值当月同比（合并1-2月）']
    title = '工业增加值当月同比（合并1-2月）'
    y_label = '%'
    save_name = '工业增加值当月同比'    
    """
    
    find_path = search_data(theme)
    find_data = pd.read_excel('cache/' + find_path, index_col=0)

    df1 = find_data.loc[:,filter_cols]
    df1 = df1.dropna()
    
    if len(df1) > show_period:
        df1 = df1[-show_period:]
    
    if use_cols is not None:
        df1.columns = use_cols
    
    # 将索引转换为每月的第一天
    if isinstance(df1.index, pd.DatetimeIndex):
        df1.index = df1.index.to_period('M').to_timestamp()
        df1.index = pd.to_datetime(df1.index)
    # 按最后一行数据排序
    df1 = df1.iloc[:, df1.iloc[-1].argsort()[::-1]]
    
    plt.figure(figsize=(12, 6))
    colors = ['#8B0000', '#00008B', '#808080']
    colors = colors[:len(df1.columns)]  # 确保颜色列表长度与列数相匹配
    
    for i, col in enumerate(df1.columns):
        # 修改为绘制条形图
        ax = plt.gca()
        ax.bar(df1.index, df1[col], color=colors[i], width=width)

    # 标注最后一期数据,并添加箭头,并根据数据大小调整偏移
    last_index = df1.index[-1]
    y_offset_dic = {}
    y_dic = {}
    for i,  col in enumerate(df1.columns):
        y = df1[col].iloc[-1]
        prev_y = df1[col].iloc[-2]  # 获取倒数第二期数据
        arrow = '↑' if y > prev_y else '↓' if y < prev_y else ''
        if arrow == '↑':
            color = 'red'
        elif arrow == '↓':
            color = 'green'
        else:
            color = 'black'
        
        if i == 0:
            y_offset_dic[i] = 0
            y_dic[i] = y
        else:
            if abs(y - y_dic[i-1]) < 0.5:
                gap = 12
            else:
                gap = 0
            y_dic[i] = y
            y_offset_dic[i] = y_offset_dic.get(i-1, 0) - gap
        offset_x = 5  # 根据数据索引动态调整x轴偏移
        
        plt.annotate(
            f'{y:.0f}{unit}{arrow}', 
            xy=(last_index, y), 
            xytext=(offset_x, y_offset_dic[i]),
            textcoords='offset points', 
            ha='left', 
            va='bottom', 
            color=color, 
            fontsize=8
            )

    # 设置图表标题和标签
    plt.title(title)
    # plt.xlabel('日期')
    plt.ylabel(y_label)
    plt.legend(df1.columns, frameon=False)

    # 仅去除右侧和上侧的边框
    ax = plt.gca()
    ax.spines['right'].set_visible(False)
    ax.spines['top'].set_visible(False)

    # 确保主定位器和数据范围匹配
    ax.xaxis.set_major_locator(mdates.YearLocator())
    ax.xaxis.set_major_formatter(FuncFormatter(yearly_formatter))
    # 确保次定位器和数据范围匹配
    ax.xaxis.set_minor_locator(mdates.MonthLocator())
    latest_month = df1.index[-1].month
    adap_formatter = monthly_adaptive_formatter[latest_month]
    ax.xaxis.set_minor_formatter(FuncFormatter(adap_formatter))

    # 设置横向刻度
    plt.xticks(rotation=0)
    plt.grid(False)
    
    dir_path = f"plot\plot_{get_today_date()}"
    dir_theme_path = f"{dir_path}\{theme}"
    ensure_folder_exists(dir_path)
    ensure_folder_exists(dir_theme_path)
    li = []
    # 将厘米转换为英寸
    for h in [9]:
        w = 15
        # h = 9
        width_inch = w / 2.54
        height_inch = h / 2.54
        plt.gcf().set_size_inches(width_inch, height_inch)
        path = f'{dir_theme_path}\{save_name}_{w}_{h}.png'
        plt.savefig(path, dpi=300, bbox_inches='tight')
        li.append(path)
    return li


def plot_monthly_sesaonal_data(theme, name, title, x_label, y_label, save_name):
    """
    theme = 'PMI'
    name = '中国:制造业PMI'
    title = '制造业PMI'
    x_label = ''
    y_label = ""
    save_name = '一、制造业PMI季节性'
    """
        
    se_data = pd.read_excel('cache/' + search_data(theme), index_col=0)

    se = se_data[name]

    se = se.dropna()
    df = pd.DataFrame(se)
    df['年'] = df.index.year
    df['月'] = df.index.month

    li = []
    for year, se in df.groupby('年'):
        se = se.set_index('月')
        se_ = se[name]
        se_.name = year
        li.append(se_)
        
    df_year = pd.concat(li,axis=1)
    df_year.sort_index(ascending=True, inplace=True)
    # 绘制折线图
    plt.figure(figsize=(12, 6))
    # 定义颜色列表
    colors = ['#8B0000', '#00008B', '#808080', '#008000']
    # 绘制折线图并指定颜色
    # 获取本年度
    current_year = datetime.now().year
    for idx, year in enumerate(df_year.columns):
        if year == current_year:
            df_year[year].plot(kind='line', ax=plt.gca(), color=colors[idx], marker='o')
        else:
            df_year[year].plot(kind='line', ax=plt.gca(), color=colors[idx])

    plt.title(title)
    plt.xticks(
        range(1,13), 
        ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'])
    plt.xlabel('')
    # plt.ylabel(y_label)
    plt.legend(title='', frameon=False, loc='upper center', bbox_to_anchor=(0.5, 1.02), ncol=4)


    if current_year in df_year.columns:
        # 增加 xytext 中的 y 坐标值，让文字更靠上
        for month, value in df_year[current_year].items():
            plt.annotate(
                f'{value:.1f}', 
                xy=(month, value), 
                xytext=(5, 10),
                textcoords='offset points', 
                ha='left', 
                va='top', 
                fontsize=8,
                color='gray',
                # bbox=dict(
                #     boxstyle='round', 
                #     facecolor='white', 
                #     edgecolor='white', 
                #     pad=0.5,
                #     alpha=0.3)
                )

    # 仅去除右侧和上侧的边框
    ax = plt.gca()
    ax.spines['right'].set_visible(False)
    ax.spines['top'].set_visible(False)

    dir_path = f"plot\plot_{get_today_date()}"
    ensure_folder_exists(dir_path)
    theme_path = f"{dir_path}\{theme}"
    ensure_folder_exists(theme_path)

    li = []
    for h in [9]:
        w = 15
        # h = 9
        width_inch = w / 2.54
        height_inch = h / 2.54
        plt.gcf().set_size_inches(width_inch, height_inch)
        # 保存图片，使用 bbox_inches='tight'
        path = f'{theme_path}\{save_name}{w}_{h}.png'
        plt.savefig(path, dpi=300, bbox_inches='tight')
        li.append(path)
    return li
        
        
def plot_compare_bar_with_last_peirod(theme, filter_cols, use_cols, title, y_label, save_name):
    
    """
    theme = '价格_CPI'
    filter_cols = [
        '中国:CPI:食品烟酒:当月同比', 
        '中国:CPI:衣着:当月同比',
        '中国:CPI:居住:当月同比',
        '中国:CPI:生活用品及服务:当月同比',
        '中国:CPI:交通和通信:当月同比',
        '中国:CPI:教育文化和娱乐:当月同比',
        '中国:CPI:其他用品和服务:当月同比',
        '中国:CPI:医疗保健:当月同比',
        ]

    title = 'CPI分项当月同比与上月对比'
    y_label = 'CPI分项'
    save_name = "二、CPI分项当月同比与上月对比"
    """
    data = pd.read_excel('cache/' + search_data(theme), index_col=0)
    tax_filter = data.loc[:,filter_cols]
    tax_filter = tax_filter.dropna()
    tax_filter.columns = use_cols
    # 获取 tax_filter 的最后两行
    last_two_rows = tax_filter.tail(2)
    last_two_rows.index = [f"{s.year}年{s.month}月" for s in last_two_rows.index]
    # 绘制横着的条形图
    plt.figure(figsize=(12, 6))
    # 设置 width 参数为 0.6，你可以根据需要调整这个值
    ax = last_two_rows.T.plot(kind='barh', color=['#8B0000', '#00008B'], width=0.6)

    # 设置图表标题和标签
    plt.title(title)
    plt.ylabel(y_label)
    # plt.xlabel('累计同比')
    # 仅去除右侧和上侧的边框
    ax = plt.gca()
    ax.spines['right'].set_visible(False)
    ax.spines['top'].set_visible(False)

    # 设置图例位置到图片底部，去掉边框线
    plt.legend(loc='upper center', bbox_to_anchor=(0.5, -0.05), fancybox=True, ncol=2, frameon=False)

    #添加数据标签
    for p in ax.patches:
        width = p.get_width()
        height = p.get_height()
        x, y = p.get_xy()
        if width >= 0:
            # 正值时注释文字靠右，设置字体大小为 8，你可以根据需要调整
            ax.annotate(f'{width:.1f}%', (x + width, y + height/2), ha='left', va='center', color='gray', fontsize=8)
        else:
            # 负值时注释文字靠左，设置字体大小为 8，你可以根据需要调整
            ax.annotate(f'{width:.1f}%', (x, y + height/2), ha='left', va='center', color='gray', fontsize=8)

    dir_path = f"plot\plot_{get_today_date()}"
    ensure_folder_exists(dir_path)
    theme_dir_path = f"{dir_path}\{theme}"
    ensure_folder_exists(theme_dir_path)
    # plt.show()

    li = []
    for h in [9]:
        w = 15
        width_inch = w / 2.54
        height_inch = h / 2.54
        plt.gcf().set_size_inches(width_inch, height_inch)
        # 保存图片，使用 bbox_inches='tight'
        path = f'{theme_dir_path}\{save_name}_{w}_{h}.png'
        plt.savefig(path, dpi=300, bbox_inches='tight')
        li.append(path)
    return li


def plot_simple_bar_by_col(theme, filter_cols, use_cols, title, y_label, save_name):
    
    """
    """
    data = pd.read_excel('cache/' + search_data(theme), index_col=0)
    tax_filter = data.loc[:,filter_cols]
    tax_filter = tax_filter.dropna()
    tax_filter.columns = use_cols
    last_two_rows = tax_filter.tail(2)
    last_two_rows.index = [s.strftime('%Y-%m-%d') for s in last_two_rows.index]
    # 绘制横着的条形图
    plt.figure(figsize=(12, 6))
    # 设置 width 参数为 0.6，你可以根据需要调整这个值
    se = last_two_rows.iloc[-1]
    ax = se.plot(kind='bar', color='#8B0000', width=0.6)

    # 设置图表标题和标签
    plt.title(title)
    plt.ylabel(y_label)
    # plt.xlabel('累计同比')
    # 仅去除右侧和上侧的边框
    ax = plt.gca()
    ax.spines['right'].set_visible(False)
    ax.spines['top'].set_visible(False)

    # 设置图例位置到图片底部，去掉边框线
    plt.legend(loc='best', fancybox=True, ncol=2, frameon=False) # 调整图例位置
    plt.xticks(rotation=90)

    #添加数据标签
    for p in ax.patches:
        width = p.get_width()
        height = p.get_height()
        x, y = p.get_xy()
        if height >= 0:
            # 正值时注释文字在柱子上方，设置字体大小为 8，你可以根据需要调整
            print("height,", height)
            ax.annotate(f'{height:.0f}', (x + width/2, y + height), ha='center', va='bottom', color='gray', fontsize=8)
        else:
            # 负值时注释文字在柱子下方，设置字体大小为 8，你可以根据需要调整
            ax.annotate(f'{height:.0f}', (x + width/2, y + 16), ha='center', va='bottom', color='gray', fontsize=8)

    dir_path = f"plot\plot_{get_today_date()}"
    ensure_folder_exists(dir_path)
    theme_dir_path = f"{dir_path}\{theme}"
    ensure_folder_exists(theme_dir_path)
    # plt.show()

    li = []
    for h in [9]:
        w = 15
        width_inch = w / 2.54
        height_inch = h / 2.54
        plt.gcf().set_size_inches(width_inch, height_inch)
        # 保存图片，使用 bbox_inches='tight'
        path = f'{theme_dir_path}\{save_name}_{w}_{h}.png'
        plt.savefig(path, dpi=300, bbox_inches='tight')
        li.append(path)
    return li


def plot_stack_col(theme, filter_cols, use_cols, title, y_label, save_name, show_period):
    
    data = pd.read_excel('cache/' + search_data(theme), index_col=0)
    filter_data = data.loc[:,filter_cols]
    use_data = filter_data.dropna()
    use_data.columns = use_cols
    df1 = use_data[-show_period:]

    df1.index = [pd.to_datetime(get_first_day_of_month(d)) for d in df1.index]
    # 按最后一行数据排序
    df1 = df1.iloc[:, df1.iloc[-1].argsort()[::-1]]

    # 分离正负数据
    df_pos = df1.applymap(lambda x: x if x >= 0 else 0)
    df_neg = df1.applymap(lambda x: x if x < 0 else 0)

    # 准备绘图数据
    bottom_pos = np.zeros(len(df1.index))
    bottom_neg = np.zeros(len(df1.index))
    
    plt.figure(figsize=(12, 6))
    ax = plt.gca()

    # 绘制负的 bar 并堆叠
    for col in df_neg.columns:
        ax.bar(df1.index.to_list(), df_neg[col], bottom=bottom_neg, 
               label=col if df_neg[col].sum() != 0 else "", width=16)
        bottom_neg += df_neg[col]

    # 绘制正的 bar 并堆叠
    for col in df_pos.columns:
        ax.bar(df1.index.to_list(), df_pos[col], bottom=bottom_pos, 
               label=col if df_pos[col].sum() != 0 else "", width=16)
        bottom_pos += df_pos[col]

    # 找出最后一期绝对值最大的三个柱状图
    last_period_data = df1.iloc[-1]
    top_3_cols = last_period_data.abs().nlargest(3).index

    bar_width = 16  # 柱子的宽度
    # 标注最后一期绝对值最大的三个柱状图
    last_index = df1.index[-1]
    # 将日期转换为 matplotlib 内部使用的浮点数
    last_index_num = mdates.date2num(last_index)
    for col in top_3_cols:
        value = df1[col].iloc[-1]
        if value >= 0:
            y = bottom_pos[-1] - df_pos[col].iloc[-1] + value / 2
        else:
            y = bottom_neg[-1] - df_neg[col].iloc[-1] + value / 2
        # 添加箭头标签
        ax.annotate(
            f'{col}{value:.0f}', 
            xy=(last_index_num, y),  # 箭头起始位置
            xytext=(last_index_num + 2 * bar_width, y),  # 文字位置
            ha='left', 
            va='bottom', 
            fontsize=8
        )
    # 仅去除右侧和上侧的边框
    ax.spines['right'].set_visible(False)
    ax.spines['top'].set_visible(False)

    # 确保次定位器和数据范围匹配
    ax.xaxis.set_major_locator(mdates.MonthLocator())
    latest_month = df1.index[-1].month
    adap_formatter = monthly_adaptive_formatter[latest_month]
    ax.xaxis.set_major_formatter(FuncFormatter(adap_formatter))

    # 设置图表标题和标签
    plt.title(title)
    plt.xlabel(' ')
    plt.ylabel(y_label)
    li = []
    
    # 获取唯一的图例条目
    handles, labels = ax.get_legend_handles_labels()
    unique_labels = []
    unique_handles = []
    for handle, label in zip(handles, labels):
        if label not in unique_labels:
            unique_labels.append(label)
            unique_handles.append(handle)

    # 显示图例
    ax.legend(
        unique_handles,
        unique_labels,
        # title='类型',
        loc='upper center',
        bbox_to_anchor=(0.5, -0.1),  # 调整位置到 x 轴下方
        ncol=3,
        fancybox=True,
        shadow=True,
        frameon=False,
    )
    
    dir_path = f"plot\plot_{get_today_date()}"
    ensure_folder_exists(dir_path)
    theme_dir_path = f"{dir_path}\{theme}"
    ensure_folder_exists(theme_dir_path)
    
    li = []
    for h in [9]:
        w = 15
        width_inch = w / 2.54
        height_inch = h / 2.54
        plt.gcf().set_size_inches(width_inch, height_inch)
        # 保存图片，使用 bbox_inches='tight'
        path = f'{theme_dir_path}\{save_name}_{w}_{h}.png'
        plt.savefig(path, dpi=300, bbox_inches='tight')
        li.append(path)
    return li
    